
package suncertify.ui;

//~--- non-JDK imports --------------------------------------------------------

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import suncertify.middle.ClientBroker;
import suncertify.middle.DirectBroker;
import suncertify.middle.RemoteClientBroker;

import suncertify.launcher.ApplicationLauncher;

//~--- JDK imports ------------------------------------------------------------

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.FileInputStream;

import java.util.ArrayList;
import java.util.Properties;

import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import suncertify.shared.DefaultConfig;
import suncertify.shared.ServerProperty;


/**
 *
 * @author jshah
 * Controller class for the UI CSRScreen, it handles all the UI events generated by <code>CSRScreen</code>
 *
 */
public class CSRScreenController implements ActionListener, ListSelectionListener, ItemListener {
    int                 toBook = -1;
    /**
     * ClientBroker      The interface which would pass on the request to server other by RMI or Direct
     */
    ClientBroker        broker;
    /**
     * CSRScreen         contains a reference of the UI CSRScreen
     */
    CSRScreen           instance;
    /**
     * rowData           contains the Data for the TableModel
     */
    ArrayList<String[]> rowData;
    int refreshRate = 20;       //default rate for refresh if none is selected
    Properties props ;
    Runnable refreshThread;

    enum colNames{

         RecordNo("RecordNo.",60), Name("NAME",200), Location("LOCATION",100), Speciality("SPECIALTY",200), Size("SIZE",50), Price("PRICE/HR",80), BookedBy("BOOKED BY",100);

         private String label;
         private int    colwidth;

         colNames(String label, int colwidth){
                this.label = label;
                this.colwidth = colwidth;
         }

         String getLabel(){
             return this.label;
         }

         int getColWidth(){
             return this.colwidth;
         }
    }
    /**
     * Constructor which has an argument of <code>CSRSCreen</code> instance, sets the <code>instance</code> for the class to operate on
     * @param instance
     */
    public CSRScreenController(CSRScreen instance) {
        this.instance = instance;
        this.props = new Properties();
        refreshThread = new RefreshThread();
        
        try {
            this.props.load(new FileInputStream(DefaultConfig.PROPERTYFILE));
        } catch (IOException ex) {
            Logger.getLogger(CSRScreenController.class.getName()).log(Level.SEVERE, "{0}ERROR READING PROPERTY FILE", ex);
        }
        if(ApplicationLauncher.mode.equals(ApplicationLauncher.STANDALONE)){
            broker = new DirectBroker();
            //saving current dblocation as default for next time
            if( broker.setDbPath(ServerProperty.getClientDBFileProp())){
                  
            }
            else{
                 JOptionPane.showMessageDialog(this.instance.getMyPane(), "DB FILE NOT ACCEPTED TRY AGAIN");
                 return;
            }
            new Thread(refreshThread).start();

        } 
        else{
            broker = new RemoteClientBroker(ClientRmiConfigController.rmiClientUrl);
          
            //saving current dblocation as default for next time
            if( !broker.setDbPath()){
                JOptionPane.showMessageDialog(this.instance.getMyPane(), "DB FILE NOT ACCEPTED TRY AGAIN");
                return;
            }
           
            
        }

    }

    
    public void itemStateChanged(ItemEvent ie){

        if(ie.getSource() == instance.getRefreshRates()){
           
                this.refreshRate = Integer.parseInt((String)instance.getRefreshRates().getSelectedItem());
            
        }

    }
    public void valueChanged(ListSelectionEvent le) {
        int[]  selectedrows = instance.getJtable().getSelectedRows();
        String row          = "";

        if (selectedrows != null) {

            // save the recordNo at index 0
            for (int index : selectedrows) {
                row    += (String) instance.getJtable().getValueAt(index, 0);
                toBook = Integer.parseInt(row);
            }
        }
    }

    /**
     * Handler for UI Events generated by all the buttons in the UI Screen
     * @param uiEvent   <code>ActionEvent</code> can be an event by search, searchAll, book or unbook button
     */
    public void actionPerformed(ActionEvent uiEvent) {
        if (uiEvent.getSource() == instance.getSearchButton()) {
            String name     = instance.getNamField().getText();
            String location = instance.getLocationField().getText();

            if (((name == null) || name.equals("")) && ((location == null) || location.equals(""))) {
                JOptionPane.showMessageDialog(instance.getMyPane(), "INVALID ENTRY");

                return;
            }

            rowData = broker.searchRecords(name, location);
            //if record not found rowData should be empty
            if (rowData.isEmpty()) {
                JOptionPane.showMessageDialog(instance.getMyPane(), "RECORD NOT FOUND, PLEASE REFRESH AND TRY AGAIN");
                return;
            }
            addRows(rowData);
        }

        if (uiEvent.getSource() == instance.getSearchAllButton()|| uiEvent.getSource()== instance.getRefreshTable()) {
            rowData = broker.searchRecords(null, null);

            if (rowData == null) {
                JOptionPane.showMessageDialog(instance.getMyPane(), "NO RECORDS FOUND, DATABASE EMPTY CONTACT ADMIN");
                return;
            }

            addRows(rowData);
        }

        if (uiEvent.getSource() == instance.getBook()) {
            boolean valid;
            try{
                valid = validateInput(instance.getCustomerID().getText());
            }
            catch(IllegalArgumentException ie)
            {
                valid = false;
            }
            
            if(valid){
                //make sure a record is selected else toBook is -1
                if(toBook < 0){
                    JOptionPane.showMessageDialog(instance.getMyPane(),"MAKE SURE YOU SELECTED A VALID RECORD FROM CSR TABLE");
                    return;
                }
                String[] row = broker.read(toBook);
                if(row == null){
                    JOptionPane.showMessageDialog(instance.getMyPane(),"RECORD NOT FOUND, REFRESH THE TABE AND SELECT THE RECORD AGAIN");
                    return;
                }
                boolean booked = true;
                try{
                    booked = this.validateInput(row[row.length-1].trim());
                }
                catch(IllegalArgumentException ie){
                    booked = false;
                }
                if(!booked){

                    //display the server side message on the UI
                    String message = broker.book(toBook, instance.getCustomerID().getText());
                    JOptionPane.showMessageDialog(instance.getMyPane(), message);
                    
                    DefaultTableModel newModel = new DefaultTableModel();
                    for( colNames c: colNames.values()){
                            newModel.addColumn(c.getLabel());
                    }
                    row = broker.read(toBook);
                    newModel.addRow(row);
                    instance.getJtable().setModel(newModel);
                    CSRScreen.setColumnWidth(instance.getJtable());
                }
                else{
                    JOptionPane.showMessageDialog(instance.getMyPane(),"ALREADY BOOKED, CANNOT BOOK UNBOOK FIRST");
                }
            }
            else{
                 JOptionPane.showMessageDialog(instance.getMyPane(),"CUSTOMER ID INPUT IS INVALID");
            }
        }

        if (uiEvent.getSource() == instance.getUnbook()) {
            //make sure a record is selected else toBook is -1
            if(toBook < 0){
               JOptionPane.showMessageDialog(instance.getMyPane(),"MAKE SURE YOU SELECTED A VALID RECORD FROM CSR TABLE");
               return;
            }
            String[] row = broker.read(toBook);
            if(row == null){
               JOptionPane.showMessageDialog(instance.getMyPane(),"RECORD NOT FOUND, REFRESH THE TABE AND SELECT THE RECORD AGAIN");
               return;
            }
            boolean booked = true;
            if(row[row.length-1].trim().length()==0){
               JOptionPane.showMessageDialog(instance.getMyPane(),"CANNOT UNBOOK A RECORD WHICH IS NOT BOOKED");
               booked = false;
               return;
            }
            if(booked){
//                if (broker.unbook(toBook) < 0) {
//                    JOptionPane.showMessageDialog(instance.getMyPane(), "UNBOOKING FAILED");
//                }

                JOptionPane.showMessageDialog(instance.getMyPane(), broker.unbook(toBook));
                DefaultTableModel newModel = new DefaultTableModel();
                for( colNames c: colNames.values()){
                            newModel.addColumn(c.getLabel());
                }
                row = broker.read(toBook);
                newModel.addRow(row);
                instance.getJtable().setModel(newModel);
                CSRScreen.setColumnWidth(instance.getJtable());
            }
        }
       
    }

    private boolean validateInput(String input)throws IllegalArgumentException, NumberFormatException{
        Integer in;
        in = Integer.parseInt(input);
        return in > 0? true: false;        
    }

    /**
     * update the TableModel by adding new Rows to JTable
     * @param rowData       contains the Data of the Rows to be added to the JTable
     */
    public void addRows(ArrayList<String[]> rowData) {
        DefaultTableModel newModel = new DefaultTableModel();
        for( colNames c: colNames.values()){
                            newModel.addColumn(c.getLabel());
        }

        for (int i = 0; i <= rowData.size() - 1; i++) {
            newModel.addRow(rowData.get(i));
        }

        instance.getJtable().setModel(newModel);
        CSRScreen.setColumnWidth(instance.getJtable());
       
    }

    /**
     * Drops the rows which are no longer required(Empty Rows) in JTable based on the size of current TableModel
     */
    public void clearTable() {
        int maxrows = instance.getJtable().getModel().getRowCount();

        for (int i = 0; i < maxrows / 2; i++) {
            instance.getTableModel().removeRow(i);
        }
    }

    /**
     * Internal class to refresh the screen displaying current contents of the db file, thread reads all the records from the dbfile
     * and adds it to the rows of JTable to
     */
    class RefreshThread implements Runnable{

        
        public void run(){
            
            while(true){
                try {
                        ArrayList<String[]> rowData = broker.searchRecords(null, null);
                        if (rowData == null) {
                            JOptionPane.showMessageDialog(instance.getMyPane(), "RECORD NOT FOUND");
                            return;
                        }
                        addRows(rowData);
                        int TIMER = CSRScreenController.this.refreshRate * 1000;
                        Thread.sleep(TIMER);
                        
                } catch (InterruptedException ex) {
                    Logger.getLogger(CSRScreenController.class.getName()).log(Level.SEVERE, "{0}REFRESH THREAD INTERRUPTED", ex);
                }
            }
        }
    }
}

